#include "ErrDump.h"

#include <stdlib.h>
#include <stdio.h>

#ifdef WIN32
#else
	#include <signal.h>
	#include <execinfo.h>
#endif

#define SIG_OK	-1
#define STACK_NUM	50

#ifdef __cplusplus
extern "C" {
#endif

static char dump_buff[2048];

#ifdef WIN32

void
install_fault_hook( )
{
}

void
dump_cur_stack( const char* dump_file)
{
}
	
#else

void (*sig_segfault) (int sig);
void (*sig_busfault) (int sig);
/* Obtain a backtrace and print it to stdout. */
void
print_trace ( int sig )
{
	void *array[ STACK_NUM ];
	size_t size;
	char **strings;
	size_t i;
	
	size = backtrace ( array,  STACK_NUM );
	strings = backtrace_symbols ( array, size );
	
	if(sig==SIGSEGV)
		sprintf( dump_buff, "\nsegmentation fault\n" );
	else if(sig==SIGBUS)
		sprintf( dump_buff, "\nbus error\n" );
	else if(sig==SIGTRAP)
		sprintf( dump_buff, "\nprocess is trapped\n" );

	sprintf( dump_buff, "%s\nthe calling stack is:\n-----------------%zd stack frames.--------------------\n", dump_buff, size );
	
	for (i = 0; i < size; i++)
		sprintf ( dump_buff, "%s%s\n", dump_buff, strings[i] );
	sprintf( dump_buff, "%s------------------end of stack----------------------\n" , dump_buff );
	
	free (strings);
	if( sig != SIG_OK )
	{
		printf( dump_buff );
		printf( "\n goto last sig hander \n" );
		if( sig == SIGSEGV )
			sig_segfault( sig );
		else if( sig == SIGBUS )
			sig_busfault( sig );
		else
		{
			printf( "\n the sig %x unknown, quit process\n", sig );
			exit( 1 );
		}
	}
}

/* A dummy function to make the backtrace more interesting. */
void
dummy_function (int sig)
{
	print_trace ( sig );
	exit(1);
}

void
install_fault_hook()
{
	struct sigaction sact;
	
	sigemptyset(&sact.sa_mask);
	sact.sa_flags = 0;
	sact.sa_handler = dummy_function;
/*	sigaction(SIGTRAP, &sact, NULL); */
	sig_segfault = sigaction(SIGSEGV, &sact, NULL);
	sig_busfault = sigaction(SIGBUS, &sact, NULL);
}

void
dump_cur_stack( const char* dump_file)
{
	print_trace( SIG_OK );
	if( dump_file )
	{
		printf( " function not implement\n%s\n", dump_buff );
	}
	else
		printf( dump_buff );
}

#endif

#ifdef __cplusplus
}
#endif

